package cn.blb.service.edu.service.impl;

import cn.blb.common.result.ResultCode;
import cn.blb.service.edu.entity.ExcelSubjectData;
import cn.blb.service.edu.entity.Subject;
import cn.blb.service.edu.entity.vo.SubjectVo;
import cn.blb.service.edu.listener.SubjectExcelListener;
import cn.blb.service.edu.mapper.SubjectMapper;
import cn.blb.service.edu.service.SubjectService;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import javafx.stage.Window;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * <p>
 * 课程科目 服务实现类
 * </p>
 *
 * @author ccl
 * @since 2022-03-17
 */
@Service
public class SubjectServiceImpl extends ServiceImpl<SubjectMapper, Subject> implements SubjectService {

    private final SubjectMapper subjectMapper;

    public SubjectServiceImpl(SubjectMapper subjectMapper) {
        this.subjectMapper = subjectMapper;
    }

    public List<SubjectVo> nestedList(){
        QueryWrapper<Subject> parentWrapper = new QueryWrapper<>();
        QueryWrapper<Subject> eq1 = parentWrapper.eq("parent_id",0);
        List<SubjectVo> subjectVos = new ArrayList<>();
        List<Subject> subjects = subjectMapper.selectList(eq1);
        subjects.forEach(e->{
            QueryWrapper<Subject> wrapper = new QueryWrapper<>();
            QueryWrapper<Subject> eq = wrapper.eq("parent_id",e.getId());
            List<Subject> subjects1 = subjectMapper.selectList(eq);

            SubjectVo subjectVo = new SubjectVo();
            subjectVo.setChildren(subjects1);
            subjectVo.setId(e.getId()).setTitle(e.getTitle());
            subjectVos.add(subjectVo);
        });
        return subjectVos;
    }

    @Override
    public void batchImport(MultipartFile file) {
        try {
            InputStream is = file.getInputStream();
            EasyExcel.read(is, ExcelSubjectData.class, new SubjectExcelListener(this)).sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
            try {
                throw new Exception(String.valueOf(ResultCode.FILE_UPLOAD_ERROR));
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
    }

    @Override
    public void saveOneSubject(List<ExcelSubjectData> list) {
        // 根据集合中对象的某个属性给集合去重
        List<ExcelSubjectData> esds = list.stream().filter(distinctByKey(ExcelSubjectData::getOneSubjectName)).collect(toList());
        // 表格所有titles
        List<String> levelOnes = new ArrayList<>();
        // 遍历获取所有表格title,添加到levelOnes
        for (ExcelSubjectData excelSubjectData : esds) {
            levelOnes.add(excelSubjectData.getOneSubjectName());
        }

        // 构建条件，查询一级标题在数据库是否存在
        QueryWrapper wrapper = new QueryWrapper();
        // 有没有相同的名称
        wrapper.select("title").in("title", levelOnes);
        // parent_id是不是等于0
        wrapper.eq("parent_id", 0);
        // 得到返回结果
        List<Subject> subs = baseMapper.selectList(wrapper);

        // 如果结果的title跟subs的一级标题一样，去重
        List<String> titls = subs.stream().map(o -> o.getTitle()).collect(Collectors.toList());
        List<ExcelSubjectData> collect = esds.stream().filter(o -> !titls.contains(o.getOneSubjectName())).collect(toList());


        // 遍历数据，插入数据库
        for (ExcelSubjectData data : collect) {
            Subject subject = new Subject();
            subject.setTitle(data.getOneSubjectName());
            subject.setParentId("0");
            baseMapper.insert(subject);
        }
        // 添加二级分类
        this.saveTwoSubject(list);
    }

    @Override
    public void saveTwoSubject(List<ExcelSubjectData> list) {
        // 遍历原始数据
        for (ExcelSubjectData subjectData : list) {
            QueryWrapper wrapper1 = new QueryWrapper();
            // 根据title获取对象
            wrapper1.eq("title", subjectData.getOneSubjectName());
            Subject selectOne = baseMapper.selectOne(wrapper1);
            // 获取一级标题id
            String pid = selectOne.getId();
            // 判断二级标题是否重复
            QueryWrapper<Subject> wrapper2 = new QueryWrapper<>();
            wrapper2.eq("title", subjectData.getTwoSubjectName());
            wrapper2.eq("parent_id", pid);
            Subject subject = this.getOne(wrapper2);
            // 如果数据库没有，添加
            if (subject == null) {
                subject = new Subject();
                subject.setTitle(subjectData.getTwoSubjectName());
                subject.setParentId(pid);
                this.save(subject);
            }
        }
    }


    // 去重方法
    private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }
}
